import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.text.DecimalFormat;

import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

public class Calculation {
	
	private static XSSFSheet ExcelWSheet;
    private static XSSFWorkbook ExcelWBook;
    private static XSSFCell xCell;
    private static XSSFRow xRow;
    private static String path = "path\\to\\excel\\file\\fileName.xlsx";
    private static String sheet = "sheetName";
    
	//This method is to set the File path and to open the Excel file, Pass Excel Path and Sheetname as Arguments to this method
    public static void setExcelFile(String Path,String SheetName) throws Exception {
    	try {
            // Open the Excel file
         FileInputStream ExcelFile = new FileInputStream(Path);
         // Access the required test data sheet
         ExcelWBook = new XSSFWorkbook(ExcelFile);
         ExcelWSheet = ExcelWBook.getSheet(SheetName);
         } catch (Exception e){
             throw (e);
         }
    }
    
  //This method is to read the test data from the Excel cell, in this we are passing parameters as Row num and Col num
    public static String getCellData(int RowNum, int ColNum) throws Exception{
           try{
        	  xCell = ExcelWSheet.getRow(RowNum).getCell(ColNum);
              String CellData = xCell.getStringCellValue();
              return CellData;
              }catch (Exception e){
                return"";
              }
    }
	
    public static void setCellData(String Result,  int RowNum, int ColNum) throws Exception    {
        try{
           xRow  = ExcelWSheet.getRow(RowNum);
           if (xRow == null)
           { xRow  = ExcelWSheet.createRow(RowNum); }
         xCell = xRow.getCell(ColNum, Row.MissingCellPolicy.RETURN_BLANK_AS_NULL);
         if (xCell == null) {
             xCell = xRow.createCell(ColNum);
             xCell.setCellValue(Result);
             } else {
                 xCell.setCellValue(Result);
             }
         		// Constant variables Test Data path and Test Data file name
               FileOutputStream fileOut = new FileOutputStream(path);
               ExcelWBook.write(fileOut);
               fileOut.flush();
             fileOut.close();
             }catch(Exception e){
                 throw (e);
         }
     }

	public static void main(String[] args) throws Exception
	{
		int [][]testSuite = {
				{0,0,0,0,0},
				{1,0,1,1,1},
				{0,1,0,0,0},
				{0,0,0,0,0},
				{0,0,1,1,1},
				{0,0,0,1,1},
				{0,0,0,1,1},
				{0,0,0,1,1}
				};

//Fault matrices, row = test case # start from first, column = fault # start from first				
//		Jewellery Store
//		{0,0,0,0,0},
//		{1,0,1,1,1},
//		{0,1,0,0,0},
//		{0,0,0,0,0},
//		{0,0,1,1,1},
//		{0,0,0,1,1},
//		{0,0,0,1,1},
//		{0,0,0,1,1}
		
//		Online Car Rental
//		{0,0,0,0,0,0,0},
//		{0,0,1,1,0,0,0},
//		{1,0,0,0,0,0,1},
//		{0,0,1,0,1,0,0},
//		{0,0,1,0,1,1,0},
//		{0,1,0,0,0,0,0},
//		{0,0,0,0,0,0,0},
//		{0,0,0,0,1,0,0},
//		{0,0,1,0,1,0,0},
//		{0,0,0,0,0,0,0},
//		{0,0,0,0,0,0,0},
//		{0,0,1,0,1,0,0}
		
//		BloodBank
//		{0,0,0,0,0,0,0,0,0,0,0,0,0},
//		{0,0,0,0,0,1,0,0,1,1,0,0,0},
//		{0,0,1,0,0,0,0,1,0,0,0,0,0},
//		{0,0,0,0,0,0,0,1,0,0,0,0,0},
//		{0,0,0,0,0,0,0,0,0,0,0,0,0},
//		{0,0,0,0,0,0,0,0,0,0,0,0,0},
//		{0,1,0,0,1,0,0,0,1,0,0,0,1},
//		{0,0,0,0,0,0,0,1,0,0,0,0,0},
//		{0,0,0,0,0,0,1,1,0,0,0,1,0},
//		{0,0,0,0,0,0,1,0,0,0,0,1,0},
//		{0,0,0,0,0,0,1,1,1,0,0,1,0},
//		{0,0,0,0,0,0,1,0,0,0,0,0,0},
//		{0,0,0,1,0,0,0,0,0,0,0,0,0},
//		{0,0,0,0,0,0,0,0,0,0,0,0,0},
//		{0,0,0,0,0,0,1,0,0,0,0,0,0},
//		{0,0,0,0,0,0,1,0,0,0,0,0,0},
//		{0,0,0,0,0,0,0,1,0,0,0,0,0},
//		{0,0,0,0,0,0,0,0,0,0,0,1,0},
//		{0,0,0,0,0,0,1,0,1,0,0,0,0},
//		{0,0,0,0,0,0,1,1,1,0,0,0,0},
//		{1,0,0,0,0,0,1,1,0,0,1,1,0},
//		{0,0,0,0,0,0,0,0,0,0,0,1,0},
//		{0,0,0,0,0,0,0,1,0,0,0,1,0},
//		{0,0,0,0,0,0,0,1,1,0,0,0,0},
//		{0,0,0,0,0,0,0,0,0,0,0,0,0}
		
		final double NUM_OF_FAULT = testSuite[0].length;
		final double NUM_OF_TC = testSuite.length;
		
		DecimalFormat numberFormat = new DecimalFormat("#.0000");
		System.out.println("");
		
		double highest = 0, lowest = 1, totalAPFD = 0, avgAPFD = 0, highestAPFDOrderingNum = 0, lowestAPFDOrderingNum = 0;
		String highestAPFDOrderingSet = "", lowestAPFDOrderingSet = "";
		
		setExcelFile(path,sheet);
				
		double[] apfd = new double[ExcelWSheet.getLastRowNum() + 1];
		
		//ExcelWSheet.getLastRowNum() + 1
		for(int row = 1; row < ExcelWSheet.getLastRowNum() + 1; row++)
		{
			String testCaseOrdering = getCellData(row,0);
			
			System.out.println("");
			System.out.println("Ordering " + (row));
			System.out.println(testCaseOrdering);
			
			String[] separatedTCNumber = testCaseOrdering.split("-");
			int[] testCase = new int[(int) NUM_OF_TC];
			
			for(int i = 0; i < NUM_OF_TC; i++)
				testCase[i] = Integer.parseInt(separatedTCNumber[i]);
			
			double total = 0;
			
			for(int j = 0; j < NUM_OF_FAULT; j++)
			{
				for(int k = 0; k < NUM_OF_TC; k++)
				{
					if ( testSuite[(testCase[k]-1)][j] == 1 )
					{
						total += (k + 1);
						break;
					}
				}
			}
			
			apfd[row] = 1 - ( (total) / ( NUM_OF_TC * NUM_OF_FAULT ) ) + ( (1) / ( 2 * NUM_OF_TC ) );
			
//			System.out.println(apfd[row] + " %");
			System.out.println(numberFormat.format(apfd[row]));
			
			if (apfd[row] > highest)
				highest = apfd[row];
			
			if (apfd[row] < lowest)
				lowest = apfd[row];
			
			totalAPFD += apfd[row];
		}
		
		int commahighest = 0, commalowest = 0;
		for(int loop = 1; loop < apfd.length; loop++)
		{
			if (apfd[loop] == highest)
			{
				if(commahighest != 0)
					highestAPFDOrderingSet = highestAPFDOrderingSet.concat(", ");
					
				highestAPFDOrderingSet = highestAPFDOrderingSet.concat(String.valueOf(loop));
				highestAPFDOrderingNum += 1;
				commahighest = 1;
			}
			
			if (apfd[loop] == lowest)
			{
				if(commalowest != 0)
					lowestAPFDOrderingSet = lowestAPFDOrderingSet.concat(", ");
				
				lowestAPFDOrderingSet = lowestAPFDOrderingSet.concat(String.valueOf(loop));
				lowestAPFDOrderingNum += 1;
				commalowest = 1;
			}
		}
		
		avgAPFD = totalAPFD / (ExcelWSheet.getLastRowNum());
		
		System.out.println("");
		System.out.println("Highest APFD:");
		System.out.println("Ordering <" + highestAPFDOrderingSet + ">.");
		System.out.println("APFD = " + highest + " %");
		System.out.println("Chances = " + ((highestAPFDOrderingNum/(apfd.length - 1))*100) + " %");
		
		System.out.println("");
		System.out.println("Lowest APFD:");
		System.out.println("Ordering <" + lowestAPFDOrderingSet + ">.");
		System.out.println("APFD = " + lowest + " %");
		System.out.println("Chances = " + ((lowestAPFDOrderingNum/(apfd.length - 1))*100) + " %");
		
		System.out.println("Average APFD = " + numberFormat.format(avgAPFD));
	}
}
